package org.ee.core.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.filter.CommonsRequestLoggingFilter;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 *针对生产环境大流量设计，特点如下：
 * <p>
 * 只输出关键 Headers（Content-Type、Authorization、User-Agent，可扩展）
 * <p>
 * 自动截断 payload，防止日志过长
 * <p>
 * GET 请求打印 query params，POST 请求根据 Content-Type 美化（JSON 或 form-data）
 * <p>
 * 可根据日志级别控制输出，方便开发/生产切换
 * @Author jokr
 * @Date 2025/8/29 11:36
 */
public class PrettyRequestBigLoggingFilter extends CommonsRequestLoggingFilter {
    private final ObjectMapper objectMapper = new ObjectMapper();

    // 最大 payload 长度，超过就截断
    private static final int MAX_PAYLOAD_LENGTH = 500;

    // 只打印关键 headers
    private static final List<String> INCLUDE_HEADERS = Arrays.asList(
            "content-type", "authorization", "user-agent"
    );

    public PrettyRequestBigLoggingFilter() {
        this.setIncludeQueryString(true);
        this.setIncludePayload(true);
        this.setIncludeHeaders(true);
        this.setIncludeClientInfo(true);
        this.setMaxPayloadLength(4096);
        this.setAfterMessagePrefix("REQUEST DATA-");
    }

    @Override
    protected void beforeRequest(HttpServletRequest request, String message) {
        // 不打印，避免重复日志
    }

    @Override
    protected void afterRequest(HttpServletRequest request, String message) {
        StringBuilder sb = new StringBuilder();
        sb.append("\n=== HTTP REQUEST BEGIN ===\n");
        sb.append("Method : ").append(request.getMethod()).append("\n");
        sb.append("URI    : ").append(request.getRequestURI()).append("\n");
        sb.append("Client : ").append(request.getRemoteAddr()).append("\n");
        sb.append("User   : ").append(request.getRemoteUser()).append("\n");

        // 打印关键 headers
        sb.append("Headers:\n");
        Collections.list(request.getHeaderNames()).forEach(name -> {
            if (INCLUDE_HEADERS.contains(name.toLowerCase())) {
                String value = request.getHeader(name);
                if ("authorization".equalsIgnoreCase(name)) {
                    value = maskAuthorization(value); // 掩码敏感信息
                }
                sb.append("  ").append(name).append(": ").append(value).append("\n");
            }
        });

        // GET 请求参数
        if ("GET".equalsIgnoreCase(request.getMethod()) && request.getQueryString() != null) {
            sb.append("Query Params:\n  ").append(request.getQueryString()).append("\n");
        }

        // POST 请求 payload
        if ("POST".equalsIgnoreCase(request.getMethod()) && message.contains("payload=")) {
            String payload = message.substring(message.indexOf("payload=") + 8).trim();
            if (payload.endsWith("]")) payload = payload.substring(0, payload.length() - 1);

            if (!payload.isEmpty()) {
                // 截断长 payload
                if (payload.length() > MAX_PAYLOAD_LENGTH) {
                    payload = payload.substring(0, MAX_PAYLOAD_LENGTH) + "...(truncated)";
                }

                sb.append("Payload:\n");

                String contentType = request.getContentType();
                if (contentType != null && contentType.contains("application/json")) {
                    try {
                        String pretty = objectMapper.writerWithDefaultPrettyPrinter()
                                .writeValueAsString(objectMapper.readTree(payload));
                        sb.append(pretty).append("\n");
                    } catch (Exception e) {
                        sb.append(payload).append("\n");
                    }
                } else if (contentType != null && contentType.contains("application/x-www-form-urlencoded")) {
                    String[] pairs = payload.split("&");
                    for (String pair : pairs) {
                        sb.append("  ").append(pair.replace("=", " : ")).append("\n");
                    }
                } else {
                    sb.append(payload).append("\n");
                }
            }
        }

        sb.append("=== HTTP REQUEST END ===");
        logger.info(sb.toString());
    }

    // 掩码 Authorization，只显示前 7 个字符
    private String maskAuthorization(String auth) {
        if (auth == null || auth.length() <= 10) return "****";
        return auth.substring(0, 7) + "****";
    }
}
